package com.example.filesystem.controller;

import cn.hutool.json.JSONException;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.example.filesystem.entity.Dir;
import com.example.filesystem.entity.FileInfo;
import com.example.filesystem.entity.Result;
import com.example.filesystem.service.IDirService;
import com.example.filesystem.service.IFileInfoService;
import com.example.filesystem.service.ISequenceService;
import com.example.filesystem.service.IUserService;
import com.example.filesystem.util.FileUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author bbyh
 * @since 2025-04-27
 */
@RestController
@RequestMapping("/dir")
@Slf4j
@Api("/文件夹接口")
public class DirController {
    @Resource
    private IDirService dirService;
    @Resource
    private IFileInfoService fileInfoService;
    @Resource
    private IUserService userService;
    @Resource
    private ISequenceService sequenceService;

    @ApiOperation("获取文件及文件夹展示列表接口")
    @PostMapping("/getDirAndFileList")
    public Result getDirAndFileList(@RequestBody Map<String, Object> map, HttpServletRequest request) {
        try {
            String username = request.getHeader("username");
            Integer parentDirId = (Integer) map.get("parentDirId");
            Integer userId = userService.getUserIdByUsername(username);

            LambdaQueryWrapper<Dir> dirLambdaQueryWrapper = new LambdaQueryWrapper<>();
            dirLambdaQueryWrapper.eq(Dir::getParentDirId, parentDirId).eq(Dir::getUserId, userId).orderByAsc(Dir::getDirName);
            List<Dir> dirList = dirService.list(dirLambdaQueryWrapper);

            LambdaQueryWrapper<FileInfo> fileInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
            fileInfoLambdaQueryWrapper.eq(FileInfo::getUserId, userId).eq(FileInfo::getDirId, parentDirId).orderByAsc(FileInfo::getFileName);
            List<FileInfo> fileInfoList = fileInfoService.list(fileInfoLambdaQueryWrapper);

            JSONObject jsonObject = new JSONObject();
            jsonObject.putOnce("dirPath", dirService.getPathOfDir(parentDirId, userId));
            jsonObject.putOnce("dirList", dirList);
            jsonObject.putOnce("fileInfoList", transferFileInfoList(fileInfoList));
            return Result.success(jsonObject, "文件及文件夹展示列表获取成功");
        } catch (JSONException e) {
            log.error(e.getMessage(), e);
            return Result.error(null, "获取文件及文件夹展示列表接口服务出错");
        }
    }

    private List<Map<String, Object>> transferFileInfoList(List<FileInfo> fileInfoList) {
        List<Map<String, Object>> res = new ArrayList<>();
        for (FileInfo fileInfo : fileInfoList) {
            Map<String, Object> map = new HashMap<>();
            map.put("fileId", fileInfo.getFileId());
            map.put("dirId", fileInfo.getDirId());
            map.put("fileMd5", FileUtil.bytesToMd5(fileInfo.getFileMd5()));
            map.put("fileName", fileInfo.getFileName());
            map.put("fileSize", fileInfo.getFileSize());
            map.put("createTime", fileInfo.getCreateTime());
            res.add(map);
        }
        return res;
    }

    @ApiOperation("添加文件夹接口")
    @PostMapping("/addDir")
    public Result addDir(@RequestBody Map<String, Object> map, HttpServletRequest request) {
        try {
            String username = request.getHeader("username");
            Integer parentDirId = (Integer) map.get("parentDirId");
            String dirName = (String) map.get("dirName");
            Integer userId = userService.getUserIdByUsername(username);

            if (dirService.getPathOfDir(parentDirId, userId).size() >= 4) {
                return Result.error(null, "添加文件夹失败，目录最多四层");
            }

            LambdaQueryWrapper<Dir> parentDirLambdaQueryWrapper = new LambdaQueryWrapper<>();
            parentDirLambdaQueryWrapper.eq(Dir::getDirId, parentDirId).eq(Dir::getUserId, userId);
            Dir parentDir = dirService.getOne(parentDirLambdaQueryWrapper);
            if (parentDir == null) {
                return Result.error(null, "添加文件夹失败，父目录不存在");
            }

            LambdaQueryWrapper<Dir> dirLambdaQueryWrapper = new LambdaQueryWrapper<>();
            dirLambdaQueryWrapper.eq(Dir::getParentDirId, parentDirId).eq(Dir::getUserId, userId).eq(Dir::getDirName, dirName);
            Dir dir = dirService.getOne(dirLambdaQueryWrapper);
            if (dir != null) {
                return Result.error(null, "添加文件夹失败，该文件夹已在当前目录下存在");
            }

            dir = new Dir();
            dir.setDirId(sequenceService.nextDirSeqVal(userId));
            dir.setParentDirId(parentDirId);
            dir.setUserId(userId);
            dir.setDirName(dirName);
            dir.setCreateTime(LocalDateTime.now());
            dirService.save(dir);
            return Result.success(null, "添加文件夹成功");
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Result.error(null, "添加文件夹接口服务出错");
        }
    }

    @ApiOperation("删除文件夹接口")
    @PostMapping("/deleteDir")
    public Result deleteDir(@RequestBody Map<String, Object> map, HttpServletRequest request) {
        try {
            String username = request.getHeader("username");
            Integer userId = userService.getUserIdByUsername(username);
            Integer dirId = (Integer) map.get("dirId");
            Dir dir = dirService.getDirByDirIdAndUserId(dirId, userId);
            if (dir == null) {
                return Result.error(null, "删除文件夹失败，该文件夹在当前目录下不存在");
            }
            dirService.removeDirRecursiveById(dirId);
            return Result.success(null, "删除文件夹成功");
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Result.error(null, "删除文件夹接口服务出错");
        }
    }

    @ApiOperation("重命名文件夹接口")
    @PostMapping("/renameDir")
    public Result renameDir(@RequestBody Map<String, Object> map, HttpServletRequest request) {
        try {
            String username = request.getHeader("username");
            Integer userId = userService.getUserIdByUsername(username);
            Integer dirId = (Integer) map.get("dirId");
            Dir dir = dirService.getDirByDirIdAndUserId(dirId, userId);
            if (dir == null) {
                return Result.error(null, "重命名文件夹失败，该文件夹在当前目录下不存在");
            }

            Integer parentDirId = (Integer) map.get("parentDirId");
            String newName = (String) map.get("newName");
            Dir sameNameDir = dirService.getDirByDirIdAndDirName(parentDirId, newName, userId);
            if (sameNameDir != null) {
                return Result.error(null, "重命名文件夹失败，该文件夹名称在当前目录下已存在");
            }

            dir.setDirName(newName);
            dirService.updateById(dir);

            return Result.success(null, "重命名文件夹成功");
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Result.error(null, "重命名文件夹接口服务出错");
        }
    }

    @ApiOperation("移动文件夹接口")
    @PostMapping("/moveDir")
    public Result moveDir(@RequestBody Map<String, Object> map, HttpServletRequest request) {
        try {
            String username = request.getHeader("username");
            Integer userId = userService.getUserIdByUsername(username);
            Integer dirId = (Integer) map.get("dirId");
            Dir dir = dirService.getDirByDirIdAndUserId(dirId, userId);
            if (dir == null) {
                return Result.error(null, "移动文件夹失败，被移动的文件夹不存在");
            }

            Integer destinationDirId = (Integer) map.get("destinationDirId");
            String dirName = (String) map.get("dirName");
            Dir sameNameDir = dirService.getDirByDirIdAndDirName(destinationDirId, dirName, userId);
            if (sameNameDir != null) {
                return Result.error(null, "移动文件夹失败，该文件夹名称在目标目录下已存在");
            }

            dir.setParentDirId(destinationDirId);
            dirService.updateById(dir);

            return Result.success(null, "移动文件夹成功");
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Result.error(null, "移动文件夹接口服务出错");
        }
    }

}
